﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LoLScrape;
using LoLScrape.Inibin;

namespace LoLEdit
{
    public partial class ctlDocumentPage : UserControl
    {
        private Dictionary<UInt32, Object> m_Dict;

        public ctlDocumentPage()
        {
            InitializeComponent();
        }

        #region Public Properties

        public Dictionary<UInt32, Object> FileDictionary
        {
            get { return m_Dict; }

            set 
            { 
                m_Dict = value;
                if (value != null) RePopulatePanels();
            }
        }

        #endregion Public Properties

        #region Public Events

        /// <summary>
        /// Standard EventArgs arguements class for events, but with an added property for tracking progress
        /// </summary>
        public class ProgressEventArgs : EventArgs
        {
            public int Progress { get; set; }
            public string Status { get; set; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);

        /// <summary>
        /// Occurs when the Document is Loading or Closing a File Dictionary
        /// </summary>
        public event ProgressEventHandler ReportingProgress;
        
        /// <summary>
        /// Raises the Reporting Progress Event
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnReportingProgress(ProgressEventArgs e)
        {
            if (ReportingProgress != null) ReportingProgress(this, e);
        }

        #endregion Public Events

        #region Public Methods

        /// <summary>
        /// Updates the segment panels visually, hiding unnecessary panels, and growing/shrinking panels as required
        /// </summary>
        public void UpdatePanels()
        {
            //This variable will be used to cache the current row index for a given segment panel
            int intIndex = 0;

            //Halt the layout drawing for the layout panel until all segment panels have been formatted
            pnlLayout.SuspendLayout();

            ProgressEventArgs e = new ProgressEventArgs();

            //Calculate the total amount of work to be done for this method
            int intCurrItem = pnlLayout.Controls.Count + (m_Dict != null ? m_Dict.Count : 0);
            int intTotalWork = (pnlLayout.Controls.Count * 2) + (m_Dict != null ? m_Dict.Count : 0);

            //Loop through every control contained in the layout panel (each segment panel)
            foreach (Control ctl in pnlLayout.Controls)
            {
                //Retrieve the Row index for this segment panel
                intIndex = pnlLayout.GetRow(ctl);

                //Cast this control into a Segment Panel (because all controls in this layout panel are segment panels)
                ctlSegmentPanel seg = (ctlSegmentPanel)ctl;
                
                //Check to see if this segment panel has any rows to display
                if (seg.RowCount == 0)
                {
                    //Nothing to display, so hide this segment panel
                    pnlLayout.RowStyles[intIndex].Height = 0;
                } //end if
                else
                {
                    //Set the height of this segment panel to the height of the segment header, and the number of rows
                    pnlLayout.RowStyles[intIndex].Height = 50 + (seg.RowCount * 25);
                } //end else

                e.Progress = (100 * (++intCurrItem)) / intTotalWork;
                e.Status = "Updating Panels...";
                OnReportingProgress(e);

            } //end foreach

            //Resume the layout drawing events for the layout panel (all segment panels formatted)
            pnlLayout.ResumeLayout();

            e.Progress = 0;
            e.Status = "";
            OnReportingProgress(e);

        } //end UpdatePanels

        #endregion Public Methods

        #region Private Methods

        private void RePopulatePanels()
        {
            //Halt the layout drawing for the layout panel until all segment panels have been formatted
            pnlLayout.SuspendLayout();
            
            //Calculate the total amount of work to be done for this method
            int intCurrItem = 0;
            int intTotalWork = (pnlLayout.Controls.Count * 2) + (m_Dict != null ? m_Dict.Count : 0);

            //Start the progress report at 0%
            ProgressEventArgs e = new ProgressEventArgs();
            e.Progress = 0;
            e.Status = "Reloading Document...";
            OnReportingProgress(e);
            
            //Loop through every segment panel in the document and clear the current row information
            foreach (Control ctl in pnlLayout.Controls)
            {
                //Cast this control into a Segment Panel (because all controls in this layout panel are segment panels)
                ctlSegmentPanel seg = (ctlSegmentPanel)ctl;

                //Clear out this segment
                if (seg.RowCount > 0)
                {
                    seg.ClearRows();
                } //end if

                e.Progress = (100 * (++intCurrItem)) / intTotalWork;
                e.Status = "Clearing existing document contents...";
                OnReportingProgress(e);
                
            } //end foreach

            //Loop through all of the data in the file dictionary, populating each of the segment panels
            foreach (KeyValuePair<UInt32, Object> item in m_Dict)
            {
                if (item.Key == 0) continue;
                RowControls row = null;
                switch (item.Value.GetType().Name)
                {
                    case "Segment01Item":
                        Segment01Item seg1 = (Segment01Item)item.Value;
                        row = pnlSegment1.AddRow(item.Key);
                        row.ValueA = seg1.ToString();
                        break;
                    case "Segment02Item":
                        Segment02Item seg2 = (Segment02Item)item.Value;
                        row = pnlSegment2.AddRow(item.Key);
                        row.ValueA = seg2.ToString();
                        break;
                    case "Segment03Item":
                        Segment03Item seg3 = (Segment03Item)item.Value;
                        row = pnlSegment3.AddRow(item.Key);
                        row.ValueA = seg3.ToString();
                        break;
                    case "Segment04Item":
                        Segment04Item seg4 = (Segment04Item)item.Value;
                        row = pnlSegment4.AddRow(item.Key);
                        row.ValueA = seg4.ToString();
                        break;
                    case "Segment05Item":
                        Segment05Item seg5 = (Segment05Item)item.Value;
                        row = pnlSegment5.AddRow(item.Key);
                        row.ValueA = seg5.ToString();
                        break;
                    case "Segment06Item":
                        Segment06Item seg6 = (Segment06Item)item.Value;
                        row = pnlSegment6.AddRow(item.Key);
                        row.ValueA = seg6.ToString();
                        break;
                    case "Segment07Item":
                        Segment07Item seg7 = (Segment07Item)item.Value;
                        row = pnlSegment7.AddRow(item.Key);
                        row.ValueA = seg7.R.ToString();
                        row.ValueB = seg7.G.ToString();
                        row.ValueC = seg7.B.ToString();
                        break;
                    case "Segment08Item":
                        Segment08Item seg8 = (Segment08Item)item.Value;
                        row = pnlSegment8.AddRow(item.Key);
                        row.ValueA = seg8.R.ToString();
                        row.ValueB = seg8.G.ToString();
                        row.ValueC = seg8.B.ToString();
                        break;
                    case "Segment09Item":
                        Segment09Item seg9 = (Segment09Item)item.Value;
                        row = pnlSegment9.AddRow(item.Key);
                        row.ValueA = seg9.X.ToString();
                        row.ValueB = seg9.Y.ToString();
                        break;
                    case "Segment10Item":
                        Segment10Item seg10 = (Segment10Item)item.Value;
                        row = pnlSegment10.AddRow(item.Key);
                        row.ValueA = seg10.X.ToString();
                        row.ValueB = seg10.Y.ToString();
                        break;
                    case "Segment11Item":
                        Segment11Item seg11 = (Segment11Item)item.Value;
                        row = pnlSegment11.AddRow(item.Key);
                        row.ValueA = seg11.R.ToString();
                        row.ValueB = seg11.G.ToString();
                        row.ValueC = seg11.B.ToString();
                        row.ValueD = seg11.A.ToString();
                        break;
                    case "Segment12Item":
                        Segment12Item seg12 = (Segment12Item)item.Value;
                        row = pnlSegment12.AddRow(item.Key);
                        row.ValueA = seg12.R.ToString();
                        row.ValueB = seg12.G.ToString();
                        row.ValueC = seg12.B.ToString();
                        row.ValueD = seg12.A.ToString();
                        break;
                    case "String":
                    default:
                        row = pnlSegment13.AddRow(item.Key);
                        row.ValueA = item.Value.ToString();
                        break;
                } //end switch

                e.Progress = (100 * (++intCurrItem)) / intTotalWork;
                e.Status = "Loading document contents...";
                OnReportingProgress(e);

            } //end foreach

            UpdatePanels();

            //Resume the layout drawing events for the layout panel (all segment panels formatted)
            pnlLayout.ResumeLayout();

            e.Progress = 0;
            e.Status = "";
            OnReportingProgress(e);

        } //end RePopulatePanels

        #endregion Private Methods

    }
}
